package tt.dz.egobus.servicemanager.core.task;

import org.quartz.*;
import tt.dz.egobus.servicemanager.core.exception.BusinessException;

import java.util.Date;

import static org.quartz.TriggerBuilder.newTrigger;
import static tt.dz.egobus.servicemanager.bean.ServiceManagerCodeStatus.SYSTEM_CODE_ERROR;

/**
 * @author Anson
 * @date 17-8-4
 * @name 基于Quartz实现任务动态管理
 * @since 1.0.6
 */
public abstract class QuartzTaskManagerImpl implements DynamicTaskManager {


    /**
     * @author Anson
     * @date 17-8-4
     * @name 获取计划任务工厂
     * @since 1.0.6
     */
    protected abstract SchedulerFactory getSchedulerFactory();

    /**
     * @author Anson
     * @date 17-8-4
     * @name 任务组名称
     * @since 1.0.6
     */
    protected abstract String getDefaultJobGroupName();

    /**
     * @author Anson
     * @date 17-8-4
     * @name trigger组名
     * @since 1.0.6
     */
    protected abstract String getDefaultTriggerGroupName();

    @Override
    public void addJob(DynamicTask task) {
        if (task != null) {
            JobDataMap jobDataMap = new JobDataMap(task.convertJobDataMap());
            this.addJob(task.getJobName(), task.getJobGroupName(),
                    task.getTriggerName(), task.getTriggerGroupName(), task.jobClass(), task.getStartTime(), jobDataMap);
        }
    }

    /**
     * @param jobName
     * @param jobClass
     * @param startTime
     * @author Anson
     * @date 17-8-4
     * @name 添加一个不能修改以及不能保证正常执行的任务
     * @since 1.0.6
     */
    public void addJob(String jobName, Class jobClass, Date startTime) {
        String groupName = this.getDefaultJobGroupName();
        String triggerGroupName = this.getDefaultTriggerGroupName();
        String triggerName = triggerGroupName + System.currentTimeMillis() + "";
        this.addJob(jobName, groupName, triggerName, triggerGroupName, jobClass, startTime, new JobDataMap());
    }


    @Override
    public void addJob(String jobName, String jobGroupName, String triggerName,
                       String triggerGroupName, Class jobClass, Date startTime, JobDataMap newJobDataMap) {
        try {
            Scheduler scheduler = getSchedulerFactory().getScheduler();
            JobKey jobKey = JobKey.jobKey(jobName, jobGroupName);
            TriggerKey triggerKey = TriggerKey.triggerKey(triggerName, triggerGroupName);
            JobDetail jobDetail =
                    JobBuilder.newJob(jobClass).withIdentity(jobKey).setJobData(newJobDataMap).build();
            SimpleTrigger trigger = (SimpleTrigger) newTrigger()
                    .withIdentity(triggerKey)
                    .startAt(startTime).build();
            scheduler.scheduleJob(jobDetail, trigger);
            startScheduler(scheduler);
        } catch (Exception e) {
            throw new BusinessException(SYSTEM_CODE_ERROR.getCodeStatus());
        }
    }


    @Override
    public void modifyJobTime(String jobName, String jobGroupName, String triggerName,
                              String triggerGroupName, Date startTime) {
        try {
            Scheduler scheduler = getSchedulerFactory().getScheduler();
            SimpleTrigger trigger =
                    (SimpleTrigger) scheduler.getTrigger(TriggerKey.triggerKey(triggerName, triggerGroupName));
            if (trigger == null) {
                return;
            }
            long oldTime = trigger.getStartTime().getTime();
            if (oldTime != startTime.getTime()) {
                JobDetail jobDetail = scheduler.getJobDetail(JobKey.jobKey(jobName, jobGroupName));
                JobDataMap jobDataMap = jobDetail.getJobDataMap();
                Class objJobClass = jobDetail.getJobClass();
                removeJob(jobName, jobGroupName, triggerName, triggerGroupName);
                addJob(jobName, jobGroupName, triggerName, triggerGroupName, objJobClass, startTime, jobDataMap);
            }
        } catch (Exception e) {
            throw new BusinessException(SYSTEM_CODE_ERROR.getCodeStatus());
        }
    }


    @Override
    public void removeJob(String jobName, String jobGroupName, String triggerName, String triggerGroupName) {
        try {
            Scheduler scheduler = getSchedulerFactory().getScheduler();
            TriggerKey triggerKey = TriggerKey.triggerKey(triggerName, triggerGroupName);
            JobKey jobKey = JobKey.jobKey(jobName, jobGroupName);
            scheduler.pauseTrigger(triggerKey);// 停止触发器
            scheduler.unscheduleJob(triggerKey);// 移除触发器
            scheduler.deleteJob(jobKey);// 删除任务
        } catch (Exception e) {
            throw new BusinessException(SYSTEM_CODE_ERROR.getCodeStatus());
        }
    }

    @Override
    public void removeJob(DynamicTaskNamespace taskNamespace) {
        this.removeJob(taskNamespace.getJobName(), taskNamespace.getJobGroupName(),
                taskNamespace.getTriggerName(), taskNamespace.getTriggerGroupName());
    }

    @Override
    public void startJobs() {
        try {
            this.startScheduler(getSchedulerFactory().getScheduler());
        } catch (SchedulerException e) {
            throw new BusinessException(SYSTEM_CODE_ERROR.getCodeStatus());
        }
    }

    @Override
    public void shutdownJobs() {
        try {
            Scheduler sched = getSchedulerFactory().getScheduler();
            if (!sched.isShutdown()) {
                sched.shutdown();
            }
        } catch (Exception e) {
            throw new BusinessException(SYSTEM_CODE_ERROR.getCodeStatus());
        }
    }

    /**
     * @param scheduler
     * @throws SchedulerException
     * @author Anson
     * @date 17-8-4
     * @name 启动计划任务
     * @since 1.0.6
     */
    private void startScheduler(Scheduler scheduler) throws SchedulerException {
        // 启动
        if (!scheduler.isShutdown()) {
            scheduler.start();
        }
    }
}
